#include <iostream>
#include <string>
#include <memory>
#include "protocol.hpp"
#include "TcpServer.hpp"
using namespace std;

enum {
    success = 1,
    divzero,
    modezero,
    unknow
};

// 计算
shared_ptr<Response> Cal(shared_ptr<Request> req) {
    shared_ptr<Response> resp = shared_ptr<Response>(new Response());
    resp->SetCode(success);
    switch (req->GetOp()) {
        case '+' :
            resp->SetResult(req->GetX() + req->GetY());
            break;
        case '-' :
            resp->SetResult(req->GetX() - req->GetY());
            break;
        case '*' :
            resp->SetResult(req->GetX() * req->GetY());
            break;
        case '/' :
            {
                if (req->GetY() == 0) {
                    resp->SetResult(-1);   
                    resp->SetCode(divzero);
                } else {
                    resp->SetResult(req->GetX() / req->GetY());
                }
                break;
            }
        case '%' :
            {
                if (req->GetY() == 0) {
                    resp->SetResult(-1);   
                    resp->SetCode(modezero);
                } else {
                    resp->SetResult(req->GetX() % req->GetY());
                }
                break;
            }
        default :
            {
                resp->SetResult(-1);
                resp->SetCode(unknow);
                break;
            }
    }
    return resp;
}


void handler_request(Socket* sockp) {
    // 一直收
    unique_ptr<Factory> fact = unique_ptr<Factory>(new Factory());
    while (true) {
        // 接收报文
        string package;
        if (!sockp->Recv(&package, 1024)) {
            break;
        }
        // 接收成功
        // 解包
        string message;
        while (Decode(package, &message)) {
            // 解包成功
            shared_ptr<Request> req = fact->BuildRequest();
            // 反序列化
            if (req->DeSerialize(message)) {
                cout << "get a request: " << req->ToString() << endl;
                // 反序列化成功
                // 计算
                shared_ptr<Response> resp = Cal(req);

                // 对resp进行序列化
                string send_message = resp->Serialize();

                // 添加报头字段
                string send_package = Encode(send_message);

                // 发送
                if (!sockp->Send(send_package)) {
                    break;
                }
            } else {
                continue;
            }

        }


    }
}


int main(int argc, char* args[]) {
    if (argc != 2) {
        cout << "Usage:\n\t" << args[0] << " local_port\n" << endl;
        return 0;
    }
    uint16_t localport = stoi(args[1]);
    unique_ptr<TcpServer> ps = unique_ptr<TcpServer>(new TcpServer(localport, handler_request));
    
    ps->Loop();
    return 0;
}
